Skip to content

Harden release workflow to build and upload deterministic pollenlevels.zip asset#71

Merged
eXPerience83 merged 1 commit intomainfrom
codex/enable-hacs-download-counter-for-integration
Feb 23, 2026
Merged

Harden release workflow to build and upload deterministic pollenlevels.zip asset#71
eXPerience83 merged 1 commit intomainfrom
codex/enable-hacs-download-counter-for-integration

Conversation

@eXPerience83
Copy link
Owner

@eXPerience83 eXPerience83 commented Feb 23, 2026

User description

Motivation

  • Ensure HACS can read a real GitHub Release asset download_count by automatically attaching a deterministic ZIP named pollenlevels.zip to each published release.
  • Prevent incorrect assets, missing downloads, or duplicate uploads by making the archive deterministic and the workflow robust to retries.

Description

  • Added a GitHub Actions workflow /.github/workflows/release-asset.yml that triggers on release (types: [published]) and workflow_dispatch for manual reruns.
  • The workflow uses minimal permissions (contents: write) and a concurrency guard release-asset-${{ github.event.release.tag_name || github.ref }} with cancel-in-progress: true to avoid duplicate uploads.
  • The job checks out via actions/checkout@v5, resolves an archive ref using release.tag_name with fallback to GITHUB_SHA, and uses git archive to produce pollenlevels.zip containing only custom_components/pollenlevels.
  • A ZIP sanity check verifies custom_components/pollenlevels/manifest.json is present before uploading with softprops/action-gh-release@v2, explicitly targeting the release tag and preserving the exact asset filename pollenlevels.zip, and hacs.json contains "zip_release": true and "filename": "pollenlevels.zip" to match HACS expectations.

Testing

  • Ran ruff check --fix --select I . and it completed successfully.
  • Ran ruff check . and it completed successfully.
  • Ran black . and formatting completed with no changes required.

Codex Task


PR Type

Enhancement


Description

  • Automate deterministic ZIP asset creation and upload for GitHub Releases

  • Configure HACS integration to recognize and track release downloads

  • Implement concurrency guards and sanity checks for robust retry handling


Diagram Walkthrough

flowchart LR
  A["Release Published"] -->|"Triggers workflow"| B["Checkout Repository"]
  B -->|"Resolve ref"| C["Build ZIP Archive"]
  C -->|"Verify structure"| D["Sanity Check"]
  D -->|"Upload asset"| E["GitHub Release"]
  F["HACS Config"] -->|"Enable tracking"| E
Loading

File Walkthrough

Relevant files
Enhancement
release-asset.yml
GitHub Actions workflow for automated release ZIP creation

.github/workflows/release-asset.yml

  • Created new GitHub Actions workflow triggered on release publication
    and manual dispatch
  • Implements concurrency guard to prevent duplicate uploads with
    tag-based grouping
  • Uses git archive to build deterministic pollenlevels.zip containing
    only custom_components/pollenlevels
  • Includes ZIP structure verification step checking for manifest.json
    presence before upload
  • Uploads asset to GitHub Release with explicit tag targeting via
    softprops/action-gh-release@v2
+46/-0   
Configuration changes
hacs.json
Configure HACS for release asset download tracking             

hacs.json

  • Added "zip_release": true flag to enable HACS release asset tracking
  • Added "filename": "pollenlevels.zip" to specify expected asset
    filename for HACS
+2/-0     

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @eXPerience83, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the release process for the "Pollen Levels" HACS integration by automating the creation and attachment of a consistent 'pollenlevels.zip' asset to GitHub Releases. This ensures that HACS can accurately track download counts and manage the integration effectively, streamlining release management and improving the reliability of asset distribution.

Highlights

  • GitHub Actions Workflow: Introduced a new GitHub Actions workflow to automate the building and uploading of a deterministic 'pollenlevels.zip' asset to GitHub Releases, triggered on release publication or manual dispatch.
  • HACS Configuration Update: Modified 'hacs.json' to include 'zip_release: true' and 'filename: "pollenlevels.zip"', aligning with HACS expectations for zip-based releases and ensuring proper asset recognition.
  • Deterministic Release Assets: Implemented logic within the workflow to ensure the 'pollenlevels.zip' asset is deterministic, preventing issues with incorrect assets, missing downloads, or duplicate uploads and improving reliability for HACS.
Changelog
  • hacs.json
    • Added "zip_release": true to enable zip-based releases.
    • Added "filename": "pollenlevels.zip" to specify the name of the release asset.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/release-asset.yml
Activity
  • The author performed 'ruff check --fix --select I .', 'ruff check .', and 'black .' to ensure code quality and formatting.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@qodo-code-review
Copy link
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Unpinned action versions

Description: The workflow uses third-party GitHub Actions referenced by mutable tags
(actions/checkout@v5 and softprops/action-gh-release@v2) instead of pinning to immutable
commit SHAs, which creates a supply-chain risk if those tags are moved or compromised.
release-asset.yml [19-46]

Referred Code
- name: Checkout
  uses: actions/checkout@v5

- name: Resolve archive ref
  id: archive_ref
  run: |
    if [ -n "${{ github.event.release.tag_name }}" ]; then
      echo "ref=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
    else
      echo "ref=$GITHUB_SHA" >> "$GITHUB_OUTPUT"
    fi

- name: Build release archive
  run: |
    git archive --format=zip \
      --output=pollenlevels.zip \
      "${{ steps.archive_ref.outputs.ref }}" \
      custom_components/pollenlevels

- name: Verify ZIP structure
  run: |


 ... (clipped 7 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Limited failure context: The workflow relies on implicit shell/command failures (e.g., git archive and unzip |
grep) without emitting actionable error context (such as missing tag/ref, missing path, or
ZIP listing) to help diagnose edge-case failures.

Referred Code
  run: |
    if [ -n "${{ github.event.release.tag_name }}" ]; then
      echo "ref=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
    else
      echo "ref=$GITHUB_SHA" >> "$GITHUB_OUTPUT"
    fi

- name: Build release archive
  run: |
    git archive --format=zip \
      --output=pollenlevels.zip \
      "${{ steps.archive_ref.outputs.ref }}" \
      custom_components/pollenlevels

- name: Verify ZIP structure
  run: |
    unzip -l pollenlevels.zip | grep -q "custom_components/pollenlevels/manifest.json"

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@eXPerience83 eXPerience83 merged commit e744e44 into main Feb 23, 2026
8 checks passed
@eXPerience83 eXPerience83 deleted the codex/enable-hacs-download-counter-for-integration branch February 23, 2026 07:37
@qodo-code-review
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Ensure full Git history

Add fetch-depth: 0 to the checkout step to ensure the full git history is
available, which is necessary for the git archive command to find release tags.

.github/workflows/release-asset.yml [19-20]

 - name: Checkout
   uses: actions/checkout@v5
+  with:
+    fetch-depth: 0
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: This is a critical fix; the git archive command would likely fail on release triggers without fetching the full git history, as the default shallow clone may not include the necessary tag information.

High
Prevent unintended release creation on manual runs

To prevent failures on manual workflow runs, add a condition to the Upload
pollenlevels.zip step so it only executes on release events.

.github/workflows/release-asset.yml [42-46]

 - name: Upload pollenlevels.zip
+  if: github.event_name == 'release'
   uses: softprops/action-gh-release@v2
   with:
     files: pollenlevels.zip
-    tag_name: ${{ github.event.release.tag_name || github.ref_name }}
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that workflow_dispatch would cause the upload step to fail or behave unexpectedly, and provides a robust solution by conditionally running the step only on release events.

Medium
  • More

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The changes to hacs.json correctly configure the integration to use a release asset for HACS installations. By setting zip_release to true and specifying the filename as pollenlevels.zip, the integration will now leverage the deterministic ZIP asset generated by the release workflow. This aligns with the PR's goal of hardening the release process and ensuring accurate download tracking. The configuration follows HACS best practices for asset-based distribution.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 615ab06ba8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

uses: softprops/action-gh-release@v2
with:
files: pollenlevels.zip
tag_name: ${{ github.event.release.tag_name || github.ref_name }}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require explicit tag for manual release asset upload

When this workflow is started via workflow_dispatch, github.event.release.tag_name is empty, so tag_name falls back to github.ref_name (typically the branch name, e.g. main). That means manual reruns upload against the wrong release target (or create an unintended release/tag) instead of repairing the published release asset for a real version tag. Add a required dispatch input for the release tag and use that value (or fail fast if no tag is provided).

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant